import { ipcMain, WebContents, IpcMainEvent } from 'electron';
import { AndroidDevice } from '@/main/adb/android-device';
import { CloseDeviceEvent, DeviceConfiguration, OpenDeviceErrorEvent, OpenDeviceSuccessEvent } from '@/type/typings';
import { spawn } from 'child_process';

type OpenDeviceEvent = {
  device: AndroidDevice;
  config: DeviceConfiguration;
};

export function startScrcpyService() {
  ipcMain.on('open-device', openDeviceListener);
}

export function stopScrcpyService() {
  ipcMain.removeListener('open-device', openDeviceListener);
}

function openDeviceListener({ sender }: IpcMainEvent, { device, config }: OpenDeviceEvent) {
  const { title, record, screen, fixed, control, touch, render, bitRate, maxSize, crop } = config;
  const { open, openMirror, filepath } = record;
  const { x, y, height, width } = crop;

  const args: string[] = [];
  if (title) {
    args.push('--window-title');
    args.push(title);
  }

  if (open) {
    if (!openMirror) {
      args.push('--no-display');
    }
    args.push('--record');
    args.push(filepath!);
  }
  if (screen) {
    args.push('--turn-screen-off');
  }
  if (fixed) {
    args.push('--always-on-top');
  }
  if (!control) {
    args.push('--no-control');
  }
  if (touch) {
    args.push('--show-touches');
  }
  if (render) {
    args.push('--render-expired-frames');
  }
  if (bitRate !== 8) {
    args.push('--bit-rate');
    args.push(`${bitRate}M`);
  }
  if (maxSize !== 0) {
    args.push('--max-size');
    args.push(`${maxSize}`);
  }
  if (height !== 0 || width !== 0) {
    args.push('--crop');
    args.push(`${height}:${width}:${x}:${y}`);
  }

  openDevice(sender, device, args);
}

function openDevice(sender: WebContents, device: AndroidDevice, args: string[]) {
  const { id } = device;
  const scrcpy = spawn('scrcpy', [...args, '-s', `${id}`]);
  let opened = false;
  let exited = false;
  let stdoutData = '';
  let hasError = false;

  scrcpy.stdout.on('data', data => {
    stdoutData += (data && data.toString()) || '';
  });

  scrcpy.stdout.on('data', () => {
    if (!hasError && !opened) {
      // 打开设备成功
      sender.send('open-success', { deviceId: id, message: stdoutData } as OpenDeviceSuccessEvent);
      opened = true;
    }
  });

  scrcpy.on('error', err => {
    hasError = true;
    sender.send('open-error', {
      deviceId: id,
      error: {
        name: err.name,
        message: err.message
      }
    } as OpenDeviceErrorEvent);
    scrcpy.kill();
  });

  scrcpy.on('close', code => {
    if (!exited) {
      exited = true;
      sender.send('device-close', { code, deviceId: id } as CloseDeviceEvent);
      scrcpy.kill();
    }
  });

  scrcpy.on('exit', code => {
    if (!exited) {
      exited = true;
      sender.send('device-close', { code, deviceId: id } as CloseDeviceEvent);
      scrcpy.kill();
    }
  });
}
